!% -SD ! Bus Station ! By Alex Mitchell (ahlec) ! Created for Interactive Fiction Writing Month ! Week 4 Submission ! This work is licensed under the Creative Commons Attribution-Noncommercial 3.0 Singapore License. !=============================================================================== Constant Story "Bus station v4"; Constant Headline "^A slightly less simple story fragment, with an NPC and an attempt at polish. ^by Alex Mitchell.^"; Include "Parser"; Include "VerbLib"; !=============================================================================== ! The game objects ! the waiting room. player starts here Object waiting_room "Waiting room" with description "You are standing in a dingy, rundown waiting room in a bus terminal. The main entrance is to the north. To the south are the bus stands. To the west you can see a row of lockers. East leads to the men's toilet. One of the few remaining payphones on the planet clings desperately to the wall beside the toilet door. In the middle of the room is a single, cold, bare metal bench.", e_to toilet, s_to stands, w_to lockers, n_to "There's a blizzard outside. You'd better stay here.", before [; Go: if(payphone.ringing==true) { print_ret "You need to hangup the phone first"; } else { if(noun == s_obj) { if(stands.bus_is_waiting==true) { return false; } else { print_ret "The bus isn't here yet. Better wait in the waiting room until it arrives."; } } else { return false; } } ], has light; Verb 'rest' * 'on' noun -> Rest; [ RestSub; if(noun == bench) { <>; } else { print_ret "Not sure how you would do that."; } ]; ! bench Object bench "bench" waiting_room with description "A cold metal bench, at least its somewhere to rest.", name 'cold' 'metal' 'seat' 'chair' 'bench', has static scenery enterable supporter; ! newspaper Object newspaper "newspaper" bench with description "A crumpled copy of today's paper. Looks like its been used to soak up some sticky liquid.", name 'paper' 'newspaper' 'news' 'scrap' 'rag', examined false, after [ ; Examine: if(self.examined == false) { print "You wonder if there's any news about the storm or your family.^"; self.examined=true; } ], before [ w1 w2; Consult: wn = consult_from; w1 = NextWord(); ! First word of subject w2 = NextWord(); ! Second word (if any) of subject if (consult_words==1 && w1=='storm' or 'weather') { print_ret "The top story is, of course, about the ice storm. The worst since 1997, the entire eastern seaboard has been locked in ice since Sunday. Airports and trains are at a standstill, and the ice has brought down powerlines and phone lines across the country.^^Further down the page, there's a small article, following up on the plane crash. Still no news about exactly how many passengers were killed. Shouldn't they know by now?"; } else if (consult_words==1 && w1=='family' or 'parents') { print_ret "Nothing about your family. Perhaps tomorrow's paper will mention something? Surely someone must have found them by now."; } else { print_ret "You can't see anything about that in the paper. Maybe try a different topic?"; } insert: if(second==payphone) { print_ret "Think about what you just said. Does that make sense?"; } ], has transparent; ! liquid on newspaper Object liquid "liquid" newspaper with description "There's some liquid soaked into the newspaper. Might be coffee, might be mud, better not to know. Seems to have left the main story, about the storm, relatively un-smudged.", name 'liquid' 'stain' 'smudge' 'mark' 'sticky', has static scenery; ! use the phone Verb 'phone' 'call' 'dial' * -> CallNobody * noun -> Call; [ CallNobodySub; print_ret "Who do you want to call?"; ]; [ CallSub; if(player in bench) { print "You can't reach the phone from here."; return false; } else { if(coin in payphone) { if(noun==home) { payphone.ringing=true; startDaemon(payphone); print_ret "Its ringing. You sure you want to do this?"; } else { print_ret "You don't know the number."; } } else { print "You need to put a coin in the phone first."; return false; } } ]; ! hang up the phone Verb 'hangup' 'putdown' * -> HangUp * noun -> HangUp; [ HangUpSub; if(noun==0 || noun==payphone) { if(payphone.ringing==true) { payphone.ringing=false; stopDaemon(payphone); remove coin; print_ret "You hangup the phone in despair."; } else { print_ret "You can't hangup if you're not calling anyone!"; } } else { print "Does that make sense?"; return false; } ]; ! phone home Object payphone "payphone" waiting_room with description "A lone payphone, looking its age, clings to the wall beside the door to the men's toilet. Surprisingly, it looks like it still works.", name 'phone' 'payphone' 'antique' 'telephone', ringing false, rings 0, daemon [; self.rings ++; if(self.rings>4) { deadflag=2; print_ret "There's a click, and someone answers.^'Alex, is that you?'^You can't believe its actually your mom answering! An almost physical wave of relief sweeps over you, and you suddenly feel... what? Its almost impossible to describe. The nagging feeling in the pit of your stomach, the dryness in your throat, the deadness behind your eyes, suddenly, they're all gone.^'Where are you? We missed our flight, and couldn't get through because of the storm. Is everything ok?'^Yes, you think, after all, everything IS going to be ok."; } else { print_ret "The phone on the other end is still ringing."; } ], has scenery static container open; ! concealed magic object to allow phoning home Object home "home" waiting_room with description "There's no place like home.", name 'home' 'family' 'parents' 'mom', has static scenery; ! the bus stand Object stands "Bus stands" with description "A row of bus stands.", ! directions n_to waiting_room, cant_go "You have second thoughts about wandering into the bus bays in the dark.", ! values for when bus arrives time_until_bus 15, ! time from start of game time_arrive_announcement 5, ! time from start of game time_bus_waits 10, ! time from arrival time_leave_announcement 5, ! time from arrival bus_is_waiting false, ! is the bus at the stand now? bus_timer 0, ! time since start of game ! getting off the bus - one warning get_off 0, ! one warning, then you can get off ! handle the bus arriving daemon [; stands.bus_timer++; if (stands.bus_is_waiting==true) { if(stands.bus_timer==stands.time_leave_announcement) { ! departure announcement print "The PA system crackles to life, and a distorted voice declares: ~The last bus to Montreal will be departing from Stand 2 in ", (stands.time_bus_waits - stands.time_leave_announcement), " minutes' time.~^"; } else if(stands.bus_timer> stands.time_bus_waits) { ! bus leaves stands.bus_timer=0; stands.bus_is_waiting=false; StopDaemon(stands); print "With a shudder and a dull rumble, the bus pulls out into the night."; if(player in bus_stand) { print "^As the bus pulls away, you wonder if you'll ever see your family again."; move busdriver to bus_highway; PlayerTo(bus_highway); } else { print "^You've missed the last bus. All you can do now is wait and hope for the best."; deadflag=3; } } } else { if(stands.bus_timer==stands.time_arrive_announcement) { ! arrival announcement print "The PA system crackles to life, and a distorted voice declares: ~The last bus to Montreal will be arriving at Stand 2 in ", (stands.time_until_bus - stands.time_arrive_announcement), " minutes' time.~^"; } else if(stands.bus_timer> stands.time_until_bus) { ! bus arrives stands.bus_timer=0; stands.bus_is_waiting=true; move bus_stand to stands; print "You hear a muffled roar as the bus pulls into the stands."; } } ! print_ret stands.bus_timer; ], before [; Exit: if(ticket in player) { print "Make sure the bus doesn't leave without you...^"; return false; } else { if(self.get_off==0) { self.get_off++; print_ret "But the bus driver has already taken your ticket. He won't let you back on without a ticket.^"; } else { print "Make sure the bus doesn't leave without you...^"; return false; } } ], has light; ! the bus in the stands Object bus_stand "bus" with description "A Greyhound bus, bound for Montreal. Looks like it will be leaving soon.", name 'bus' 'coach' 'greyhound', before [; Enter: if(ticket in player) { return false; } else { print_ret "You need a ticket to get on the bus!"; } ], has enterable static; ! the men's toilet Object toilet "Men's toilet" with description "The men's toilet smells like a men's toilet. A row of urinals occupies one wall. Along the opposite wall are several cubicles, all locked except one, which is missing its door.", w_to waiting_room, has light; ! the row of locked cubicles Object cubicles "cubicles" toilet with description "The cubicles look, and smell, like they haven't been washed for years.", name 'cubicles' 'stalls' 'locked', has static scenery; ! the doorless cubicle Object cubicle "cubicle" toilet with description "One cubicle's door has been ripped from its hinges. You see a glint of something metalic on the floor.", name 'broken' 'missing' 'cubicle' 'stall' 'doorless', before [; Examine: if(coin in cubicle) { move coin to toilet; } ], has static scenery container; ! 25 cents Object coin "coin" cubicle with description "An old 25 cent piece.", name 'glint' 'metalic' 'coin' 'quarter' '25 cent piece', has; ! the row of urinals Object urinals "urinals" toilet with description "The urinals have seen better days.", name 'urinals' 'urinal', has static scenery; ! the row of lockers Object lockers "Lockers" with description "This small alcove contains a row of storage lockers.", e_to waiting_room, has light; ! this locker can be opened with the key Object locker "locker" lockers with description "A standard locker.", name 'locker' 'lockers' 'storage', with_key key has static scenery container openable lockable locked; ! inside the locker... Object diary "diary" locker with description "A small diary. The handwriting looks very familiar. You suddenly feel a wave of nausea, and look away.", tries 0, can_read false, before [; Examine: if(self.can_read==true && parent(Player)==seat) { print "Sitting in the comfort of the seat, the warmth of the bus heater starting to drive away the winter chill, you finally feel comfortable enough to open the diary.^^Glancing through the entries, you stop at Friday's entry.^^~Friday: another big fight with mom and dad. Why do they want me to come with them to Montreal? What's the big deal about having a 'family weekend' anyway? Fine, let them go by themselves. Hope they get caught in a storm, then I won't have to bother about them.~^^Why were you so stupid? Of course, rationally you know the storm had nothing to do with you (right?), but still, you can't help feeling that its your fault.^^~Saturday: missed their call, why do they keep checking on me? Don't think I'll bother calling back, waste of energy.^^Sunday 8pm: yeah, yeah, I know, flight is coming in at 10pm, make sure the cat has been fed and do the dishes, even when they're not here they're nagging.^^Sunday 11pm: still no news, the flight left on time, why doesn't the airline know what's happening?^^Monday 5am: just heard, plane went down near Ottawa, all passengers dead, why can't they confirm if they were on board?^^Monday 6pm: still no news, phone lines to Montreal are down, heard the storm is going to continue until Wednesday. Its all my fault, why did I have to say that to them?^^Tuesday: I don't know what else to do, buses are running again but no flights, and still no word. I have just enough for a ticket, I'll go there and find out for myself.~^^That's the latest entry, just before you left for the bus station. And now here you are, on the bus. Nothing else you can do except wait..."; deadflag=3; return true; } else { return false; } Take, Remove: if(self.tries<1) { self.tries++; print_ret "As you start to pick up the diary, you are overcome with a strong sense of foreboding. You quickly put the diary back in the locker."; } else { print "Taking a deep breath, you grasp the diary and pick it up. "; if(ticket in diary) { print "There seems to be something between the pages. "; } return false; } Drop, Insert: if(diary in player) { print_ret "Despite your queasiness about reading it, you can't bare to leave the diary behind."; } Open: if(diary in player) { if(ticket in diary) { print "Something slips out from between the pages of the diary. "; move ticket to parent(player); } return false; } else print_ret "You'll have to take the diary first."; ], name 'diary' 'book' 'journal', has container openable; ! the bus on the highway Object bus_highway "In the front of the bus (on the way to Montreal)" with description "The highway stretches on forever into the night.", s_to back_of_bus, out_to "The bus is moving, you'd better not get off now.", name 'bus' 'front', before [; Exit: print_ret "The bus is moving, you'd better not get off now."; ], has light; Object back_of_bus "In the back of the bus (on the way to Montreal)" with description "The highway stretches on forever into the night.", n_to bus_highway, out_to "The bus is moving, you'd better not get off now.", name 'bus' 'back', before [; Exit: if (noun==back_of_bus) { print_ret "The bus is moving, you'd better not get off now."; } else { return false; } ], has light; Object seat "seat" back_of_bus with description "A plush bus seat, with broken seatbelt.", name 'seat' 'chair' 'bench', has static scenery supporter enterable; ! inventory objects ! bus ticket Object ticket "ticket" diary with description "A one-way ticket for the 00:15 bus to Montreal.", name 'ticket' 'bus ticket', before [; insert: if(second==payphone) { print_ret "It doesn't seem to fit."; } ], has ; ! key to the locker Object key "key" with description "A small key, looks like it might fit into a storage locker.", name 'key', before [; insert: if(second==payphone) { print_ret "You try your best to jam the key in the phone, but to no avail."; } ], has ; ! ipod Object ipod "ipod" with description "Second gen ipod. Still works, amazingly.", name "ipod", daemon [; print_ret "Your ipod is droning on in the background."; ], react_before [; Listen: if(noun==nothing) if(self has on) { <>; } else { print_ret "The only sound you can hear is the blizzard outside, relentlessly pounding snow against the roof of the bus station."; } ], before [; Listen: if (self has on) { print_ret "Your ipod is inexplicably playing some 80's retro europop which you don't seem to remember loading into it."; } else { print_ret "You need to switch it on first."; } SwitchOn: StartDaemon(ipod); return false; SwitchOff: StopDaemon(ipod); return false; insert: if(second==payphone) { print_ret "I don't think so."; } ], has switchable; ! NPCs ! borrowed from IBG [ TalkSub; if (noun == player) print_ret "Talking to yourself is the first sign of madness."; if (RunLife(noun,##Talk) ~= false) return; print_ret "At the moment, you can't think of anything to say."; ]; Verb 'talk' 't//' 'converse' 'chat' 'gossip' * 'to'/'with' creature -> Talk * creature -> Talk; Class NPC with life [; Answer,Ask,Order,Tell: print_ret "Just use T[ALK] [TO ", (the) self, "]."; ], has animate; NPC busdriver "Bus Driver" bus_stand with name 'driver' 'gus', description "The bus driver looks like he hasn't gotten up from his seat in years.", first_time true, initial [; ! first time if(self.first_time==true) { print "The bus driver's eyes follow you as you get on the bus. He gives no other sign of being alive."; self.first_time=false; } else { if(busdriver in bus_stand) { print_ret "The driver is sitting in his seat, and seems to be dozing. Or dead. Wait, he's definitely dozing, you can hear him snoring."; } else { print_ret "The driver is sitting in his seat, eyes glued to the road."; } } ], times_spoken_to 0, life [; Give, Show: if(noun==ticket) { print "The bus driver takes your ticket. He glances at it and then stuffs it into the inside pocket of his jacket. "; remove ticket; return true; } else { return false; } Talk: switch (self.times_spoken_to) { 0: if(ticket in player) { print "The bus driver asks for your ticket. You hand it to him. He glances at it and then stuffs it into the inside pocket of his jacket. "; remove ticket; } else { print "There is no response. "; } self.times_spoken_to = self.times_spoken_to+1; return true; 1: if(busdriver in bus_highway) { print "The bus driver grunts but keeps his eyes on the road."; } else { print "There is no response. "; } self.times_spoken_to = self.times_spoken_to+1; return true; 2: if(busdriver in bus_highway) { print "You tap the driver on the shoulder. The snow lashing across the windscreen is blinding in the headlights, and you can't stop thinking about your family.^^Before you can say anything, you feel the sadness welling up inside you. Glancing at you for a second, the driver realizes that something's wrong.^^~Don't worry, we'll get there safely, I've been doing this route for years, in much worse weather. Why don't you go sit in the back of the bus and read a book or something, pretty soon you'll fall asleep and we'll be there before you know it.~^"; self.times_spoken_to = self.times_spoken_to+1; diary.can_read=true; return true; } else { return false; } default: return false; } ], has animate; ! just because Verb 'xyzzy' * -> xyzzy; [ xyzzySub; print_ret "Nothing happens."; ]; ! just because Verb 'panic' * -> panic; [ panicSub; print_ret "That's understandable."; ]; !=============================================================================== ! Entry point routines [ Initialise; location = bench; move key to player; move ipod to player; player.description = "You are wearing a grey hoodie, jeans and converse all-stars, hands stuffed defiantly into your jean pockets."; StartDaemon(stands); print_ret "^^ Its been two days now. You can't believe that it really happened. They were supposed to get back on Sunday night, but ever since the storm, there's been no word. Finally, you decide that you need to find out for yourself..."; ]; [ DeathMessage; print "The End"; ]; !=============================================================================== ! Standard and extended grammar Include "Grammar"; !===============================================================================